//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package impl

import (
	"context"

	"atomgit.com/openlinksaas-org/ssh-proxy/gen_code"
	"github.com/google/uuid"
)

type PortforwardApiImpl struct{}

func (s *PortforwardApiImpl) PortforwardClosePost(ctx context.Context, req gen_code.PortforwardClosePostRequest) (gen_code.ImplResponse, error) {
	if req.Token != token {
		return gen_code.ImplResponse{
			Code: 500,
			Body: &gen_code.ErrInfo{
				ErrMsg: "wrong token",
			},
		}, nil
	}
	info, ok := clientMap.Load(req.Id)
	if !ok {
		return gen_code.ImplResponse{
			Code: 500,
			Body: &gen_code.ErrInfo{
				ErrMsg: "miss client",
			},
		}, nil
	}
	client := info.(*ClientInfo)
	fcInfo, ok := client.forwardMap.Load(req.ForwardId)
	if !ok {
		return gen_code.ImplResponse{
			Code: 500,
			Body: &gen_code.ErrInfo{
				ErrMsg: "miss port forward",
			},
		}, nil
	}
	fcInfo.(*ForwardClient).Close()
	client.forwardMap.Delete(req.ForwardId)
	return gen_code.ImplResponse{
		Code: 200,
		Body: req.ForwardId,
	}, nil
}

func (s *PortforwardApiImpl) PortforwardListPost(ctx context.Context, req gen_code.PortforwardListPostRequest) (gen_code.ImplResponse, error) {
	if req.Token != token {
		return gen_code.ImplResponse{
			Code: 500,
			Body: &gen_code.ErrInfo{
				ErrMsg: "wrong token",
			},
		}, nil
	}
	info, ok := clientMap.Load(req.Id)
	if !ok {
		return gen_code.ImplResponse{
			Code: 500,
			Body: &gen_code.ErrInfo{
				ErrMsg: "miss client",
			},
		}, nil
	}
	client := info.(*ClientInfo)
	retList := []gen_code.PortForwardInfo{}
	client.forwardMap.Range(func(key, value any) bool {
		fc := value.(*ForwardClient)
		retList = append(retList, gen_code.PortForwardInfo{
			ForwardId:  key.(string),
			RemoteAddr: fc.RemoteAddr,
			LocalAddr:  fc.LocalAddr,
			Listen:     string(fc.ListenType),
		})
		return true
	})
	return gen_code.ImplResponse{
		Code: 200,
		Body: retList,
	}, nil
}

func (s *PortforwardApiImpl) PortforwardOpenPost(ctx context.Context, req gen_code.PortforwardOpenPostRequest) (gen_code.ImplResponse, error) {
	if req.Token != token {
		return gen_code.ImplResponse{
			Code: 500,
			Body: &gen_code.ErrInfo{
				ErrMsg: "wrong token",
			},
		}, nil
	}
	info, ok := clientMap.Load(req.Id)
	if !ok {
		return gen_code.ImplResponse{
			Code: 500,
			Body: &gen_code.ErrInfo{
				ErrMsg: "miss client",
			},
		}, nil
	}
	client := info.(*ClientInfo)
	fc, err := NewForwardClient(client.client.realClient, req.LocalAddr, req.RemoteAddr, LISTEN_TYPE(req.Listen))
	if err != nil {
		return gen_code.ImplResponse{
			Code: 500,
			Body: &gen_code.ErrInfo{
				ErrMsg: err.Error(),
			},
		}, nil
	}
	fcId := uuid.NewString()
	client.forwardMap.Store(fcId, fc)
	return gen_code.ImplResponse{
		Code: 200,
		Body: fcId,
	}, nil
}
